package br.requisiteworks.requisito.modelo;

import java.util.Collection;
import java.util.Iterator;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

import br.requisiteworks.modelo.Funcionario;
import br.requisiteworks.modelo.Projeto;
import br.requisiteworks.util.Entidade;
import br.requisiteworks.util.validacao.Nome;

/**
 * <p>
 * Definicao abstrata de um requisito
 * 
 * @author Mikhail Domanoski
 * 
 * @version 1, 01/04/2010
 * 
 */
@Entity
@Table(name = "tbl_requisito")
public class Requisito extends Entidade {
	/**
	 * Possiveis estados dos requisitos
	 */
	public enum Estado {
		// TODO verificar estados nos casos de uso
		NOVO, REALIZADO
	};

	/**
	 * Numero do requisito
	 */
	@Id
	@Column(name = "num_requi")
	@GeneratedValue(strategy = GenerationType.AUTO)
	protected int numero;
	/**
	 * Nome/titulo do requisito
	 */
	@Nome
	@Column(name = "nom_requi")
	protected String nome;

	/**
	 * Local onde o arquivo esta salvo
	 */
	@Column(name = "tex_local_arqui", nullable = true)
	protected String local;

	/**
	 * Nome do arquivo que sera informado ao usuario
	 */
	@Column(name = "nom_arqui", nullable = true)
	protected String nomeArquivo;

	/**
	 * Estado atual do requisito
	 */
	@Column(name = "nom_estad")
	@Enumerated(EnumType.STRING)
	protected Estado estado = Estado.NOVO;

	/**
	 * Funcionario responsavel pela elaboracao do requisito
	 */

	@ManyToOne
	@JoinColumn(name = "num_funci", nullable = true)
	protected Funcionario responsavel;

	/**
	 * Projeto ao qual o requisito pertence
	 */
	@ManyToOne
	@JoinColumn(name = "num_proje")
	@NotNull
	protected Projeto projeto;

	/**
	 * Tipo do requisito
	 */
	@ManyToOne
	@JoinColumn(name = "num_tipo_requi")
	protected TipoRequisito tipo;

	@OneToMany(targetEntity = AtributoRequisito.class, cascade = CascadeType.ALL, mappedBy = "requisito")
	protected Collection<AtributoRequisito> atributos;

	public int getNumero() {
		return numero;
	}

	public void setNumero(int numero) {
		this.numero = numero;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public Estado getEstado() {
		return estado;
	}

	public void setEstado(Estado estado) {
		this.estado = estado;
	}

	public Funcionario getResponsavel() {
		return responsavel;
	}

	public void setResponsavel(Funcionario responsavel) {
		this.responsavel = responsavel;
	}

	public Projeto getProjeto() {
		return projeto;
	}

	public void setProjeto(Projeto projeto) {
		this.projeto = projeto;
	}

	public TipoRequisito getTipo() {
		return tipo;
	}

	public void setTipo(TipoRequisito tipo) {
		this.tipo = tipo;
	}

	public Collection<AtributoRequisito> getAtributos() {
		return atributos;
	}

	public void setAtributos(Collection<AtributoRequisito> atributos) {
		this.atributos = atributos;
	}

	public String getLocal() {
		return local;
	}

	public void setLocal(String local) {
		this.local = local;
	}

	public String getNomeArquivo() {
		return nomeArquivo;
	}

	public void setNomeArquivo(String nomeArquivo) {
		this.nomeArquivo = nomeArquivo;
	}

	@Override
	public String toString() {
		final int maxLen = 5;
		StringBuilder builder = new StringBuilder();
		builder.append("Requisito [numero=");
		builder.append(numero);
		builder.append(", nome=");
		builder.append(nome);
		builder.append(", projeto=");
		builder.append(projeto);
		builder.append(", atributos=");
		builder.append(atributos != null ? toString(atributos, maxLen, builder)
				: null);
		builder.append("]");
		return builder.toString();
	}

	private String toString(Collection<?> collection, int maxLen,
			StringBuilder builder) {
		builder.append("[");
		int i = 0;
		for (Iterator<?> iterator = collection.iterator(); iterator.hasNext()
				&& i < maxLen; i++) {
			if (i > 0)
				builder.append(", ");
			builder.append(iterator.next());
		}
		builder.append("]");
		return builder.toString();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == this)
			return true;
		if (obj == null)
			return false;
		if (obj instanceof Requisito) {
			return ((Requisito) obj).numero == this.numero;
		}

		return false;
	}

	@Override
	public int hashCode() {
		int result = 0;
		result += 31 * this.nome.hashCode();
		result += 31 * this.numero;
		return result;
	}

}
